using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace ColumnDatabase
{
	public abstract class AbstractColumn<T> : IColumn
	{
		private const int ExtraFields = 1024;
		private readonly int _index;
		private readonly BinaryReader _br;
		private readonly BinaryWriter _bw;
		private readonly FileStream _streamRead;
		private readonly FileStream _streamWrite;
		private long _size = 0;

		public AbstractColumn(int index, string file)
		{
			_streamRead = new FileStream(file, FileMode.OpenOrCreate, FileAccess.Read, FileShare.ReadWrite);
			_streamWrite = new FileStream(file, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);
			_size = _streamWrite.Length;
			_br = new BinaryReader(_streamRead);
			_bw = new BinaryWriter(_streamWrite);
			_index = index;
		}

		public int Index { get { return _index; } }
		public bool Contains(long index) { return true; }
		public T this[long index]
		{
			get
			{
				_streamRead.Position = index * FieldSize;
				return GetValue(_br);
			}
			set
			{
				long pos = index * FieldSize;
				if (_size < pos + FieldSize)
				{
					_streamWrite.SetLength((index + 1 + ExtraFields) * FieldSize);
					_size = _streamWrite.Length;
				}

				_streamWrite.Position = index * FieldSize;
				SetValue(_bw, value);
			}
		}

		internal abstract int FieldSize { get;}
		internal abstract void SetValue(BinaryWriter bw, T value);
		internal abstract T GetValue(BinaryReader br);
	}
}